package com;

import java.io.IOException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import com.alibaba.fastjson.JSON;
import org.smartboot.http.HttpRequest;
import org.smartboot.http.enums.HttpMethodEnum;

/**
 * http 工具类(基于httpclient4.3.x,且不能出现重复的httpcore或者httpclient包)
 *
 * @author guojian
 */
public class HttpUtils {

    private static final Log log = LogFactory.getLog(HttpUtils.class);

    private static BasicCookieStore cookieStore = new BasicCookieStore();
    private static RequestConfig globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.DEFAULT).build();
    private static CloseableHttpClient commonHttpclient = HttpClients.custom().setDefaultRequestConfig(globalConfig).setDefaultCookieStore(cookieStore).build();
    private static CloseableHttpClient sslHttpClient = null;

    private static String DEFAULT_CONTENT_TYPE = "application/octet-stream";

    static {
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, new TrustManager[]{new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }

                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }

                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            }}, new SecureRandom());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
        sslHttpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).setSSLSocketFactory(socketFactory).build();
    }


    public static CloseableHttpResponse doGetProcess(HttpRequest request, String url) {
        HttpGet httpGet = new HttpGet(url);
        setTargetHeader(request, httpGet);
        try {
            CloseableHttpResponse response = sslHttpClient.execute(httpGet);
            //return EntityUtils.toByteArray(response.getEntity());
            return response;
        } catch (Exception e) {
            log.debug(HttpUtils.class + ": get请求发送失败! " + e.getMessage() + "--URL: " + url);
        }
        return null;
    }


    public static String JsonPost(String url, String json) {
        HttpPost httpPost = new HttpPost(url);
        setJsonHeads(httpPost);
        String responseMessage = StringUtils.EMPTY;
        try {
            if (json != null) {
                httpPost.setEntity(new StringEntity(json, "UTF-8"));
            }
            CloseableHttpResponse response = commonHttpclient.execute(httpPost);
            responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
        } catch (Exception e) {
            log.debug(HttpUtils.class + ": post 请求发送失败! " + e.getMessage() + "--URL: " + url);
        }
        log.debug("http post response: " + responseMessage);
        return responseMessage;
    }


    //List<NameValuePair> nameValuePairs = convertMapParamsToList(nameValues);
    public static CloseableHttpResponse doPostProcess(HttpRequest request, String url, HttpEntity entity) {
        HttpPost httpPost = new HttpPost(url);
        setTargetHeader(request, httpPost);
        try {
            if (entity != null) {
                httpPost.setEntity(entity);
            }
            CloseableHttpResponse response = sslHttpClient.execute(httpPost);
            //return EntityUtils.toByteArray(response.getEntity());
            return response;
        } catch (Exception e) {
            e.printStackTrace();
            log.debug(HttpUtils.class + ": post 请求发送失败! " + e.getMessage() + "--URL: " + url);
        }
        return null;
    }

    public static CloseableHttpResponse doHttpProcess(HttpRequest request, String url, HttpEntity entity) {
        HttpUriRequest httpUriRequest = RequestBuilder.create(request.getMethod())
                .setUri(url)
                .setEntity(entity).build();
        setTargetHeader(request, httpUriRequest);
        try {
            return HttpClients.createSystem().execute(httpUriRequest);
        } catch (IOException e) {
            log.debug(" doHttpProcess error :  " + e.getMessage());
        }
        return null;
    }


    /**
     * 参数类型转换
     *
     * @param nameValues
     * @return
     */
    public static List<NameValuePair> convertMapParamsToList(Map<String, String> nameValues) {
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        if (nameValues != null) {
            for (String name : nameValues.keySet()) {
                nvps.add(new BasicNameValuePair(name, nameValues.get(name)));
            }
        }
        return nvps;
    }

    /**
     * 设置请求的头部
     *
     * @param request
     */
    private static void setCommonHeads(HttpUriRequest request) {
        List<Header> headers = new ArrayList<Header>();
        headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36"));
        headers.add(new BasicHeader("Content-Type", "application/x-www-form-urlencoded"));
        headers.add(new BasicHeader("Connection", "keep-alive"));
        headers.add(new BasicHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"));
        headers.add(new BasicHeader("Cache-Control", "no-cache"));
        Header[] headersObject = new Header[headers.size()];
        request.setHeaders(headers.toArray(headersObject));
    }


    public static void setTargetHeader(HttpRequest request, HttpUriRequest targetRequest) {
        for (String headerName : request.getHeaderNames()) {
            String headerValue = request.getHeader(headerName);
            targetRequest.setHeader(new BasicHeader(headerName, headerValue));
        }
        targetRequest.removeHeaders("Content-Length");
        targetRequest.removeHeaders("ETag");
        targetRequest.removeHeaders("Last-Modified");
        targetRequest.setHeader(new BasicHeader("Cache-Control", "no-cache"));
    }


    public static Integer getContentLength(HttpRequest request) {
        Integer contentLength = -1;
        for (String headerName : request.getHeaderNames()) {
            String headerValue = request.getHeader(headerName);
            if (headerName.equalsIgnoreCase("content-length")) {
                try {
                    contentLength = Integer.parseInt(headerValue);
                } catch (NumberFormatException e) {
                    contentLength = -1;
                }
            }
        }
        return contentLength;
    }

    private static void setJsonHeads(HttpUriRequest request) {
        List<Header> headers = new ArrayList<Header>();
        headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36"));
        headers.add(new BasicHeader("Content-type", "application/json; charset=utf-8"));
        headers.add(new BasicHeader("Accept", "application/json"));
        headers.add(new BasicHeader("Connection", "keep-alive"));
        headers.add(new BasicHeader("Cache-Control", "no-cache"));
        Header[] headersObject = new Header[headers.size()];
        request.setHeaders(headers.toArray(headersObject));
    }

    public static void main(String[] args) {
        JSONObject object = new JSONObject();
        object.put("name", "guojian");
        object.put("age", 12);
        String ss = JsonPost("http://localhost:9080/json", object.toJSONString());
        System.out.println("ss = " + ss);
    }

}
